// getline获取一行的时候不带换行符。33分钟的一个细节

#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <cstdlib>
#include "Logger.hpp"
#include <string.h>
#include <map>
using namespace std;
//业务由上层实现
using callback=function<string(string& word,const string& whoip ,uint16_t whoport)>;
static const int gdefaultsockfd = -1;

class udpserver
{
public:
    udpserver(uint16_t port,callback cb)
        : _socket(gdefaultsockfd),
          _port(port),
          _isruning(0),
          _cb(cb)
    {
    }
    void Init()
    {
        _socket = socket(AF_INET, SOCK_DGRAM, 0); // 创建套接字
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local)); // 清空字符串
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = htonl(INADDR_ANY);        // 绑定本机的任意IP
        int n =bind(_socket, (sockaddr *)&local, sizeof(local)); // 绑定套接字
        if (n < 0)
        {
            
            exit(2);
        }
    }
    void start()
    {
        //所有的服务都是死循环
        _isruning =true;
        while(true)
        {
            //接收信息
            char news [1024];
            news[0]=0;
            //保存发送方的信息
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t n=recvfrom(_socket,&news,sizeof(news),0,(struct sockaddr *)&peer,&len);
            if(n<0)
            {
                cout<<"接收失败"<<endl;
                exit(3);
            }
            //接收成功
            uint16_t cilentport=ntohs(peer.sin_port);
            string cilentip =inet_ntoa(peer.sin_addr);
            news[n]=0;//设置反斜杠0
            string word=news;
            string echo_string=_cb(word,cilentip,cilentport);
            sendto(_socket,echo_string.c_str(),sizeof(echo_string),0,(struct sockaddr*)&peer,len);
    
        }
        _isruning = false;
    }
    
     void Stop()
    {
        _isruning = false;
    }
    ~udpserver()
    {

    }

private:
    int _socket;
    uint16_t _port; // 端口号
    bool _isruning;
    callback _cb;
};